package com.douziit.meilianoa.base.utils.file;

import com.douziit.meilianoa.base.annotation.OSSField;
import com.douziit.meilianoa.base.enums.ResponseCode;
import com.douziit.meilianoa.base.exception.TipException;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * OSS授权才能读取的存储
 *
 * @author douzisong
 * @date 2016年12月21日
 */
@Service
public class OSSPrivateStorage {
    private static final Logger logger = LoggerFactory.getLogger(OSSPrivateStorage.class);

    /**
     * 文件存储目录
     */
    @Value("${upload.file.path}")
    private String baseDir;
    @Value("${server.port}")
    private String port;


    /**
     * 下载
     *
     * @param response
     * @param fileName
     * @throws IOException
     */
    public void download(HttpServletResponse response, String fileName) throws IOException {

        if (StringUtils.isBlank(fileName)) {
            throw new TipException(ResponseCode.PARAM_INFO);
        }
        String fullPath = baseDir  + "/" + fileName;
        File file = new File(fullPath);
        logger.debug("read public file:{}, file path:{}", fileName, file.getPath());
        if (!file.exists()) {
            // 如果文件不存在，则直接返回
            logger.error("download public file, file not exist:{}", fileName);
            return;
        }
//        String fileExt = fileId.substring(fileId.lastIndexOf(".") + 1).toLowerCase();
//        if ("png".equals(fileExt)) {
//            response.setContentType("image/png");
//        } else if ("jpg".equals(fileExt) || ".jpeg".equals(fileExt)) {
//            response.setContentType("image/jpeg");
//        } else if ("gif".equals(fileExt)) {
//            response.setContentType("image/gif");
//        } else if ("pdf".equals(fileExt)) {
//            response.setContentType("application/pdf");
//        } else if ("doc".equals(fileExt) || "docx".equals(fileExt)) {
//            response.setContentType("application/x-download");
//        }

        response.setContentType("application/x-download");
        response.setContentType("image/png");

        OutputStream out = response.getOutputStream();
        byte[] buffer = new byte[2048];
        FileInputStream input = new FileInputStream(file);

        // 依次读取文件内容并输出
        try {
            int num = 0;
            while ((num = input.read(buffer)) > 0) {
                out.write(buffer, 0, num);
            }
        } catch (IOException ex) {
            logger.error("read public file exception:{}", fileName, ex);
            throw new TipException(ResponseCode.SYSTEM_ERROR);
        } finally {
            try {
                if (input != null) {
                    input.close();
                }
            } catch (IOException e) {
            }
        }
        out.flush();
        out.close();
    }

    /**
     * 存储文件
     *
     * @param input
     * @param fileName
     */
    public String saveFile(InputStream input, String fileName)
            throws IOException {

        File upload = new File(baseDir);
        if (!upload.exists()) {
            upload.mkdirs();
        }

        return UploadDocumentUtil.uploadFile(input, fileName, baseDir);
    }

    /**
     * 存储原文件
     *
     * @param input
     * @param fileName
     */
    public String saveOriginalFile(InputStream input, String fileName)
            throws IOException {

        File upload = new File(baseDir);
        if (!upload.exists()) {
            upload.mkdirs();
        }

        return UploadDocumentUtil.uploadOriginalFile(input, fileName, baseDir);
    }

    /**
     * 获取路径
     *
     * @param fileid
     * @return
     */
    public String buildUrl(String fileid) {
        String path = "/upload/" + fileid;
        return path;
    }

    /**
     * 根据对象组织完整路径
     * 为对象中需要组织文件路径的属性添加  @OSSField 注解
     *
     * @param obj 对象
     * @author wh
     */
    public void buildUrlUtil(Object obj) {
        try {

            List<Field> fields = new ArrayList<>();
            Class c = obj.getClass();
            while (c != null) {
                fields.addAll(Arrays.asList(c.getDeclaredFields()));
                c = c.getSuperclass();
            }
            for (Field f : fields) {
                f.setAccessible(true);
                // 判断属性上是否有OSSField注解
                OSSField ossField = f.getAnnotation(OSSField.class);
                if (ossField == null) {
                    continue;
                }
                // 获取初始的值
                String value = (String) f.get(obj);
                StringBuilder result = new StringBuilder();
                if (StringUtils.isNotBlank(value)) {
                    // 分别组织完整路径
                    String[] fileArr = value.split(",");
                    for (String file : fileArr) {
                        if (StringUtils.isNotBlank(file)) {
                            if (file.startsWith("http")) {
                                result.append(file).append(",");
                            } else {
                                result.append(buildUrl(file)).append(",");
                            }
                        }
                    }
                    if (result.length() > 0) {
                        f.set(obj, result.substring(0, result.length() - 1));
                    } else {
                        f.set(obj, "");
                    }
                } else {
                    f.set(obj, "");
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
            throw new TipException(ResponseCode.SYSTEM_ERROR);
        }
    }

    /**
     * 解析对象，只保留路径中的主要数据
     * 为对象中需要组织文件路径的属性添加  @OSSField 注解
     *
     * @param object
     */
    public void resolveUrlUtil(Object object) {
        try {
            List<Field> fields = new ArrayList<>();
            Class c = object.getClass();
            while (c != null) {
                fields.addAll(Arrays.asList(c.getDeclaredFields()));
                c = c.getSuperclass();
            }
            for (Field field : fields) {
                field.setAccessible(true);
                OSSField ossField = field.getAnnotation(OSSField.class);
                if (ossField == null) {
                    continue;
                }
                String value = (String) field.get(object);
                if (StringUtils.isNotEmpty(value)) {
                    StringBuilder result = new StringBuilder();
                    // 获取新对象中属性值的fileid列表
                    String[] fileidArr = value.split(",");
                    for (String fileid : fileidArr) {
                        if (fileid.startsWith("http")) {
                            //int start = fileid.indexOf(baseDir) + baseDir.length();
                            int start = fileid.indexOf("upload/") + "upload/".length();
                            int stop = fileid.indexOf("?", start);
                            if (stop < start) {
                                stop = fileid.length();
                            }
                            result.append(fileid, start, stop).append(",");
                        } else {
                            result.append(fileid).append(",");
                        }
                    }
                    field.set(object, result.substring(0, result.length() - 1));
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new TipException(ResponseCode.SYSTEM_ERROR);
        }
    }

}
